# 原件

import os
from locust import HttpUser, task, between, events
from config.all_paths import get_root_path
from config.global_variable import ENV_DICT
from utils.file_handling.excel_handling import ExcelUtil
from utils.interface_auth.auth_tool import Authentication
from utils.performance_tool.config_loader import load_config
from utils.performance_tool.load_shapes import SHAPE_MAP
from utils.request_tool.send_request import RequestSender
from utils.time_tool.time_control import parse_duration


excelName = 'data/case_excel/wutong/uat/医生账号相关接口.xlsx'
testData = ExcelUtil(os.path.join(get_root_path(), excelName)).read_excel()


# 加载配置
env = '' # 这个可以入参
role = '' # 这个可以入参
profile_name = ''  # 这个可以入参

config = load_config('test_wt','doctor')
profile_config = config['profiles'].get(profile_name, {})

@events.test_start.add_listener
def init_test(env, **kwargs):
    """测试初始化"""
    print(f"\n=== 启动 {profile_name} 测试 ===")
    print(f"目标环境: {env}")
    print(f"基准URL: {config['env'].get('url')}")

@events.test_stop.add_listener
def finalize_test(env, **kwargs):
    """测试收尾"""
    print("\n=== 测试结果摘要 ===")
    print(f"总请求数: {env.stats.total.num_requests}")
    print(f"失败率: {env.stats.total.fail_ratio:.2%}")



class BaseUser(HttpUser):
    wait_time = between(0.5, 2)
    abstract = True

    def on_start(self):
        self.s = Authentication(ENV_DICT.get('username'),
                               ENV_DICT.get('password'),
                               ENV_DICT.get('url'),
                               ).auth_wutong()

class BaselineUser(BaseUser):
    """恒定负载"""
    @task
    def health_check(self):
        RequestSender().send_request(self.s, testData[0])

class StressUser(BaseUser):
    """峰值压力"""
    @task(5)
    def create_data(self):
        RequestSender().send_request(self.s, testData[0])

class ConcurrencyUser(BaseUser):
    """瞬时并发"""
    @task
    def update_resource(self):
        resource_id = profile_config.get("concurrency_key")
        self.client.put(f"/resources/{resource_id}")

class WaveUser(BaseUser):
    """波浪型负载"""
    @task
    def wave_task(self):
        self.client.get("/api/wave-test")

# 动态测试类
class DynamicTestClass(eval(profile_config.get("user_class", "BaselineUser"))):
    pass

# 负载形状配置
# 选择负载形态，如果没有，就默认选择constant模式，即恒定负载
class CustomLoadShape(SHAPE_MAP[profile_config.get("load_shape", "constant")]):
    # 含义：表示在某个阶段（stage）中需要运行的用户总数。
    # 作用：用于定义在特定时间段内，系统需要承载的用户数量。
    # 示例：如果某个阶段的 shape_users 设置为 50，那么在该阶段结束时，系统中应该有 50 个用户在运行。
    shape_users = profile_config.get("users", 1)
    # 含义：表示用户生成的速率，单位是“每秒生成的用户数”。
    # 作用：用于控制用户生成的速度，确保用户数量按照预定的速率逐步增加。
    # 示例：如果 spawn_rate 设置为 10，那么每秒会生成 10 个用户，直到达到 shape_users 指定的用户总数。
    spawn_rate = profile_config.get("spawn_rate", 1)
    # 含义：表示某个阶段的持续时间，单位通常是秒。
    # 作用：用于定义每个阶段的持续时间，即在这个时间段内，用户数量会按照 spawn_rate 逐步增加到 shape_users。
    # 示例：如果某个阶段的 shape_duration 设置为 30 秒，那么这个阶段会持续 30 秒，在这 30 秒内，用户数量会逐步增加到目标值。
    shape_duration = parse_duration(profile_config.get("duration", "1m"))
    # 含义：表示整个测试过程中的不同阶段（stage）的集合。
    # 作用：用于定义测试的整个流程，包括每个阶段的用户数量、生成速率、持续时间等。
    # 示例：在这个例子中，shape_stages 是一个列表，每个元素是一个字典，定义了每个阶段的 duration（持续时间）、users（用户总数）和 spawn_rate（生成速率）。
    '''
    class CustomLoadShape(LoadTestShape):
    shape_stages = [
        {"duration": 10, "users": 10, "spawn_rate": 10},
        {"duration": 30, "users": 50, "spawn_rate": 10},
        {"duration": 60, "users": 100, "spawn_rate": 10},
    ]

    def tick(self):
        run_time = self.get_run_time()
        for stage in self.shape_stages:
            if run_time < stage["duration"]:
                return (stage["users"], stage["spawn_rate"])
        return None
    '''
    shape_stages = profile_config.get("stages", [])

# 暴露给Locust的配置
class TestScenario(DynamicTestClass):
    pass

def get_shape_class():
    return CustomLoadShape


if __name__ == '__main__':
    """
    # 运行波浪型测试
    PERF_PROFILE=wave locust -f locustfile.py --headless --run-time 10m

    # 运行压力测试
    PERF_PROFILE=stress locust -f locustfile.py --headless -u 1000 -r 100

    # 查看完整选项
    locust -f locustfile.py --help
    """